/**
* Functionality for "scribble-privileges" UI widget.
*
* @package Scribble
*/
var ScribbleAuthWidget = function(el) {

	// Properties
	this.guid = "saw-"+(Math.round(Math.random()*1000000000));
	this.roleSelector;
	this.privilegesContainer;
	this.dataField = el;
	var config;
	this.fieldName = el.attr('name');
	el.attr('name', '');

	// Extract config
	var rawConfig = el.attr('scribblewidget:config');
	var m = /resourceId=([^,]*)/.exec(rawConfig)
	config = {
		resourceId: m.length>1 ? m[1] : ''
	};

	// Create the role selector
	this.roleSelector = $('<select><option value="">Select a role to assign privileges to ...</option></select>');
	this.roleSelector.bind('click', {widget: this}, this.openRoleSelector);
	this.roleSelector.bind('change', {widget: this}, this.selectRole);
	this.roleSelector.insertBefore(this.dataField);

	// Create DIV container for holding the privileges input fields
	this.privilegesContainer = $('<div></div>');
	this.privilegesContainer.insertBefore(this.dataField);

	// Pre-populate the fields container with any existing privilege data
	var privilegeData = $.evalJSON(this.dataField.val());
	for(var i in privilegeData.assignments) {
		this.addPrivilegeFields(i, privilegeData.assignments[i]);
	}
}

/**
* Add input fields for the specified role, and pre-populate using the data in
* "assignment".
*
* @param string Role ID
* @param object Role's assignments (as generated by
* ScribbleAuthWidget::getResourcePrivileges())
* @return void
*/
ScribbleAuthWidget.prototype.addPrivilegeFields = function(roleId, assignment) {

	var privilegeData = $.evalJSON(this.dataField.val());
	var privileges = privilegeData.privileges;
	var role = privilegeData.roles[roleId];
	var eRoleTitle = $('<div></div>').html(role.title).html();
	var widgetId = this.guid+'-privileges-'+roleId;
	if($('#'+widgetId).size()>0) {
		return false;
	}

	var html = '<table id="'+widgetId+'" roleid="'+roleId+'" class="privileges"><caption>'+eRoleTitle+' &#160; ( <a href="#" rel="remove">remove</a> )</caption>';
	html += '<thead><tr><th class="pcol-first">&#160;</th><th>Allow</th><th>Deny</th><th>Inherit</th></tr></thead>';
	html += '<tbody>';
	for(var i in privileges) {
		var pid = privileges[i].id;
		var ePname = $('<div></div>').html(privileges[i].name).html();
		var ePdesc = $('<div></div>').html(privileges[i].description).html();
		html += '<tr>';
		html += '<td class="pcol-first"><span>'+ePname+'</span><p>'+ePdesc+'</p></td>';
		html += '<td><input type="radio" name="'+this.fieldName+'['+roleId+']['+pid+']" value="allow" '+(assignment[pid]==='allow' ? 'checked="checked"' : '')+' /></td>';
		html += '<td><input type="radio" name="'+this.fieldName+'['+roleId+']['+pid+']" value="deny" '+(assignment[pid]==='deny' ? 'checked="checked"' : '')+'/></td>';
		html += '<td><input type="radio" name="'+this.fieldName+'['+roleId+']['+pid+']" value="inherit" '+(!assignment[pid] || assignment[pid]==='inherit' ? 'checked="checked"' : '')+'/></td>';
		html += '</tr>';
	}
	html += '</tbody>';
	html += '</table>';
	var tbl = $(html);
	this.privilegesContainer.append(tbl);
	$('#'+widgetId+' caption a[rel=remove]').bind('click', {widget:this}, function(ev) {
		var widget = ev.data.widget;
		widget.deselectRole($(this).parents('table.privileges').attr('roleid'));
		ev.preventDefault();
	});
	return true;
}

ScribbleAuthWidget.prototype.deselectRole = function(roleId) {
	this.roleSelector.children('option').each(function(i, el) {
		if($(el).val()===roleId) {
			$(el).attr('disabled', '');
		}
	});
	var pData = $.evalJSON(this.dataField.val());
	delete pData.assignments[roleId];
	this.dataField.val($.toJSON(pData));
	this.removePrivilegeFields(roleId);
}

/**
* Loads roles from the server for display in the role selector.
*
* In this method "this" refers to the selector element. To access the widget
* instance use "ev.data.widget".
*
* @param Event Click event
* @return void
*/
ScribbleAuthWidget.prototype.openRoleSelector = function(ev) {

	// Load roles from server, if not already done so
	var selector = $(this);
	var widget = ev.data.widget;
	if(selector.find('option').length<2) {
		selector.addClass('server-busy');
		$.post(Buan.UrlCommand.createUrl('scribble', 'auth', 'role'), {}, function(roles) {
			var privilegeData = $.evalJSON(widget.dataField.val());
			for(var i=0; i<roles.length; i++) {
				var opt = $('<option value="'+roles[i].id+'"></option>').html(roles[i].title);
				if(privilegeData.roles[roles[i].id]) {
					opt.attr('disabled', 'disabled');
				}
				else {
					var tmp = {};
					tmp[roles[i].id] = roles[i];
					privilegeData.roles = $.extend({}, privilegeData.roles, tmp);
				}
				selector.append(opt);
			}
			widget.dataField.val($.toJSON(privilegeData));
			selector.removeClass('server-busy');
		}, 'json');
	}
}

/**
* Remove the privileges fields for the specified role.
*
* @param string Role GUID
* @return void
*/
ScribbleAuthWidget.prototype.removePrivilegeFields = function(roleId) {
	$('#'+this.guid+'-privileges-'+roleId).remove();
}

/**
* This handles choices made form the role-selector dropdown and adds a set of
* field inputs for the selected role.
*
* In this method "this" refers to the selector element. To access the widget
* instance use "ev.data.widget".
*
* @param Event
* @return void
*/
ScribbleAuthWidget.prototype.selectRole = function(ev) {

	var selector = this;
	var widget = ev.data.widget;
	
	widget.addPrivilegeFields(this.options[this.selectedIndex].value, {});
	this.options[this.selectedIndex].disabled = 'disabled';
	this.selectedIndex = 0;
}